<?php

namespace App\Service\CommodityService;

use App\Model\CommodityModel\StockInfoUser;
use App\Service\AppService\MyDate;
use App\Service\BaseService;
use App\Service\Code\Normal;
use Hyperf\DbConnection\Db;
use Hyperf\Task\Annotation\Task;
use App\Service\InterfaceService\BbcBestGoodsServiceInterface;
use App\Model\CommodityModel\CommodityOptimizationBbc;
use App\Model\CommodityModel\SupplierCommodityTag;
use App\Model\PssModel\TemplateDelivery;
use App\Service\OrderService\OrderQueryService\QueryGoodsMicService;
use App\Model\PssModel\Business;

class BbcBestGoodsService extends BaseService implements BbcBestGoodsServiceInterface
{
    protected $alisa_table;
    //百分率基数
    const BASE_PRICE_RATE       = 1.00;
    //小数点位数
    const BASE_SCALE_TYPE       = 4;
    //金额计算精度
    const BASE_FLOAT            = 3;
    
    /**
     * 获取原始商品价格信息
     * @param int $bid
     * @param array $SkuIDs
     * @param int $is_router_user
     */
    public function getDispatchBackUpGoodsList( $bid = 0, $SkuIDs = [],$is_router_user = 0)
    {
        $where = [];
        //正常优选逻辑
        if( $is_router_user == 0 ) {
            $string = implode("','",$SkuIDs);
            $_where[] = "cop.BuID = {$bid} AND cop.IsInit = 1 AND cop.SkuID IN ('{$string}')";
        } else {
            //路由供应商商品渠道逻辑
            $string = implode("','", $SkuIDs);
            $_where[] = "cop.BuID = {$bid} AND cop.IsInit = 1 AND cop.SupplierSKUCode IN ('{$string}')";
        }
        
        //处理取路由模式下单字段
        $_fields_skucode = $is_router_user == 1 ? "SupplierSKUCode" : "SKUCode";
        
        $_where[] = "stock.isDeleted = 0";
        $_where[] = "stock.Number > 0";
        $_where[] = "stock.IsHasPrice =1";
        $_where[] = "scb.isDeleted = 0";
        $_where[] = "scb.SaleType = 1";
        $_where[] = "scb.UpstreamSaleType = 1";
        $_where[] = "cop.CommodityStatus  = 1";
        
        $table  = CommodityOptimizationBbc::instance()->getTableByBuID($bid)->getTable();
        $list   = CommodityOptimizationBbc::instance()->getTableByBuID($bid)
        ->from($table." as cop")
        ->select([
            Db::raw('csb.ID as SkuID'),
            Db::raw("cop.{$_fields_skucode} AS skuCode"),
            Db::raw("cop.SKUCode"),
            'csb.BarCode',
            Db::raw('csb.Name as GoodsName'),
            Db::raw("csb.FreightTemplateID AS freightTemplateID"),
            Db::raw("cop.SupplierSKUID AS supplierSKUID"),
            Db::raw('cop.SupplierSKUCode as supplierSKUCode'),
            'cop.IsSaleFirst',
            'cop.IsInit',
            'cop.PriceRuleType',
            'cop.PriceScaleRule',
            'cop.SpecList',
            Db::raw("IFNULL(cds.Images,'') AS Images"),
            Db::raw("u.Name AS UnitName"),
            Db::raw("stock.ID AS stockInfoID"),
            Db::raw("stock.BatchNo AS batchNo"),
            Db::raw("stock.Number AS number"),
            Db::raw("stock.BatchID AS batchID"),
            'stock.CalibrationPeriodTime',
            Db::raw("IFNULL(u_stock.StockRemainNumber,0) AS StockRemainNumber"),
            Db::raw("stock.LimitBuyCount as limitBuyCount"),
            Db::raw('scb.SupplierCommoditySkuCode as supplierCommoditySkuCode'),
            Db::raw('scb.SupplierCommodityType as supplierCommodityType'),
            Db::raw('scb.SupplierCommodityKey as supplierCommodityKey'),
            Db::raw('scb.PriceControlType'),
            Db::raw('scb.LimitOrControlPrice'),
            Db::raw('scb.HSCode as hsCode'),
            Db::raw('csb.MarketPrice'),
            Db::raw('scb.IsHaveTaxRate as isHaveTaxRate'),
            Db::raw("IFNULL(scb.TaxRate,0.000) AS taxRate"),
            Db::raw('scb.DeliveryMethod AS deliveryMethod'),
            Db::raw('scb.DefaultStock AS defaultStock'),
            Db::raw('scb.DeclarePlanCode AS declarePlanCode'),
            Db::raw("w.ID AS warehouseID"),
            Db::raw('w.IsCombineOrders AS isCombineOrders'),
            Db::raw('w.WarehouseAccount AS warehouseAccount'),
            Db::raw('w.WarehouseType AS warehouseType'),
            Db::raw('w.WarehouseCode AS warehouseCode'),
            Db::raw('w.WarehouseName AS warehouseName'),
            Db::raw('w.CanModifyStock AS canModifyStock'),
            Db::raw('w.JsonBody'),
            Db::raw("s.ID AS supplierID"),
            Db::raw('s.SupplierCode as supplierCode'),
            Db::raw('s.ThirdPartyPlatformCode as thirdPartyPlatformCode'),
            Db::raw('s.SupplierName as supplierName'),
            Db::raw('s.EnterpriseName as enterpriseName'),
            Db::raw('s.EnterpriseCode as enterpriseCode'),
            Db::raw('s.OrderDeclare as orderDeclare'),
            Db::raw('s.PayDeclare as payDeclare'),
            Db::raw('s.OrderDockMode as orderDockMode'),
            Db::raw('scb_cus.Country as DeclareCountry'),
            Db::raw('scb_cus.CountryCode as DeclareCountryCode'),
            Db::raw('scb_cus.Currency as DeclareCurrency'),
            Db::raw('scb_cus.CurrencyCode as DeclareCurrencyCode'),
            Db::raw('scb_cus.MeasurementUnit as DeclareMeasurementUnit'),
            Db::raw('scb_cus.MeasurementUnitCode as DeclareMeasurementUnitCode'),
            Db::raw('scb_cus.DeclareBarCode as DeclareDeclareBarCode'),
            Db::raw('scb_cus.Function as DeclareFunction'),
            Db::raw('scb_cus.Specifications as DeclareSpecifications'),
            Db::raw('scb_cus.DeclareSKUCode as DeclareDeclareSKUCode'),
            Db::raw('scb_cus.DeclareCommodityName as DeclareDeclareCommodityName'),
            's.IsSettingFreight',
            's.IsSettingFreightTemplate',
            Db::raw('s.FreightTemplate as SupplierFreightTemplate'),
            Db::raw('scb.FreightTemplate as FreightTemplate'),
            Db::raw('csb.Weight as weight'),
            Db::raw('scb.ConSumptionTaxRate as conSumptionTaxRate'),//消费税率
            Db::raw('scb.ConSumptionPrice as conSumptionPrice'),//消费税预警金额
        ])
        ->join("commodityarchives_s2b as csb","csb.ID","=","cop.SkuID")
        ->leftJoin("commoditydescription_s2b as cds",function($join){
            $join->on("cds.CommodityInfoID","=","csb.ID")
            ->where("cds.IsDeleted",0);
        })
        ->join("stockinfo_s2b as stock","stock.ID","=","cop.StockInfoID")
        ->join("suppliercommodity_s2b as scb","scb.ID","=","stock.SupplierCommodityID")
        ->join("warehouseinfo_s2b as w","w.ID","=","stock.WarehouseID")
        ->join("suppliercompany_s2b as s","s.ID","=","w.SupplierID")
        ->leftJoin("classifyinfo_s2b as f_class","f_class.ID","=","csb.FirstClassificationID")
        ->leftJoin("classifyinfo_s2b as s_class","s_class.ID","=","csb.SecondClassificationID")
        ->leftJoin("classifyinfo_s2b as t_class","t_class.ID","=","csb.ThirdClassificationID")
        ->leftJoin("brandinfo_s2b as b","b.ID","=","csb.BrandID")
        ->leftJoin("countryinfo_s2b as c","c.ID","=","csb.CountryID")
        ->leftJoin("unitinfo_s2b as u","u.ID","=","csb.UnitID")
        ->leftJoin("stockinfouser_s2b as u_stock",function($join) use($bid) {
            $join->on("u_stock.StockID","=","stock.ID")
            ->where("u_stock.BuID",$bid)
            ->where("u_stock.IsDisable",0)
            ->where("u_stock.StockRemainNumber",'>',0);
        })
        ->leftJoin("suppliercommoditycustominfo_s2b as scb_cus",function($join){
            $join->on("scb_cus.SupplierCommodityID","=","cop.SupplierSKUID")
            ->where("scb_cus.IsDeleted",0);
        })
        ->whereRaw(implode(" AND ", $_where))
        ->orderBy("cop.IsSaleFirst","desc")//优选售卖
        ->orderBy("cop.BatchSpecMinSinglePrice","asc")//价格最低
        ->get()
        ->toArray();
        $listMap = [];
        
        $SkuIDKey = $is_router_user ? 'skuCode' : 'SkuID';
        foreach ($list as $item ) 
        {
            $specList = @json_decode($item['SpecList'],true);
            $specList = array_map(function( & $value) {
                $value['SpecificationNum'] = (int)$value['SpecificationNum'];
                return $value;
            },$specList);
            
            $item['SpecList'] = $specList;
            $listMap[$item[$SkuIDKey]][$item['IsSaleFirst']][]= $item;
            unset($item);
        }
        return $listMap;
    }
    
    /**
     * skucodes,skuids
     * 获取优选商品数据，全量不带分页
     * 下单调度、授权通知、供应商商品消息变化
     * @param array $param
     * @Task
     */
    public function getDispatchGoodsList( $param = [] )
    {
        $res = $this->getWhereParameters($param);
        if( $res['code'] != Normal::SUC ) {
            return $res;
        }
        
        $where = $res['data'];
        $bid = $param['bid'] ? $param['bid'] : 0 ;
        $query = $this->getBestGoodsQuery($bid,$where);
        $dataList = $this->getLastQuery($bid,$query,$where)->get()->toArray();
        $dataList = $this->getDataList($param,$dataList);
        return Normal::returnCode(Normal::SUC,"获取成功",$dataList);
    }
    
    /**
     * 协程处理多渠道用户最新商品授权情况
     * @param array $param
     * @Task
     */
    public function getCopAuthGoodsList( $param = [] )
    {
        $bidsMap = array_column($param,null,'bid');
        $bids = array_keys($bidsMap);
        if( empty($bids) ) {
            return Normal::returnCode(Normal::FAIL,"用户bids组不能为空");
        }
        
        $result = [];
        $count = count($bidsMap);
        $wg = new \Hyperf\Utils\WaitGroup();
        $wg->add($count);
        foreach ($bidsMap as $item )
        {
            co(function () use ($wg,$item,& $result )
            {
                $bid = $item['bid'];
                $param = [
                    'bid'       => $bid,
                    'IDS'       => $item['IDS'], 
                    'isArchive' => $item['isArchive']
                ];
                $res = $this->getWhereParameters($param);
                if( $res['code'] != Normal::SUC ) {
                    $result[$bid] = [];
                } else {
                    $where = $res['data'];
                    $query = $this->getBestGoodsQuery($bid,$where);
                    $dataList = $this->getLastQuery($bid,$query,$where)->get()->toArray();
                    $dataList = $this->getDataList($param,$dataList);
                    $result[$bid] = $dataList;
                }
                $wg->done();
            });
        }
        $wg->wait();
        return Normal::returnCode(Normal::SUC,"处理成功",$result);
    }
    
    /**
     * 获取优选列表数据，带分页参数
     */
    public function getBestGoodsPageList( $param = [] )
    {
        $res = $this->getWhereParameters($param);
        if( $res['code'] != Normal::SUC ) {
            return $res;
        }
        
        $where = $res['data'];
        $limit = $param['limit'] ?? 15;
        $page  = $param['page'] ?? 0;
        $bid = $param['bid'] ? $param['bid'] : 0 ;
        
        //查询全局价格最低商品
        $query      = $this->getBestGoodsQuery($bid,$where);
        
        //授权分页
        $pageInfo   = $this->getLastQuery($bid,$query,$where)->paginate($limit,['*'], 'page', $page,true)->toArray();
        $pageInfo['data']   = $this->getDataList($param,$pageInfo['data']);
        return Normal::returnCode(Normal::SUC,"获取成功",$pageInfo);
    }
    
    /**
     * 查询优选授权总商品数量
     * @param array $param
     * @Task
     */
    public function getBestGoodsCount( $param = [] )
    {
        $res = $this->getWhereParameters($param);
        if( $res['code'] != Normal::SUC ) {
            return $res;
        }
        
        $where = $res['data'];
        $bid = $param['bid'] ? $param['bid'] : 0 ;
        $query = $this->getBestGoodsQuery($bid,$where);
        $count = $this->getLastQuery($bid,$query,$where)->count();
        return Normal::returnCode(Normal::SUC,"获取成功",['count'=>$count]);
    }
    
    /**
     * 组装数据报文
     * @param array $param
     * @param array $dataList
     */
    public function getDataList( $param = [] , $pageData = [])
    {
        if( empty($pageData) ) {
            return $pageData;
        }
        //查询优先售卖商品
        $skuIds = array_column($pageData,'SkuID');
        $skuIds = implode(",", $skuIds);
        $bid    = $param['bid'] ?? 0 ;
        $where = [
            "BuID = {$bid}",
            "SkuID in ({$skuIds})",
            "IsSaleFirst = 1"
        ];
        $SaleDataList = $this->getSaleFirstQuery($bid,$where);
        $SaleDataList = array_column($SaleDataList,null,'SkuID');
        $normalIDs  = array_column($pageData,'SupplierCommodityID');
        $saleIDs    = array_column($SaleDataList,'SupplierCommodityID');
        $allIDs     = array_merge($normalIDs,$saleIDs);
        $stockIDs   = array_column($pageData,'StockInfoID');
        $saleStockIDs   = array_column($pageData,'StockInfoID');
        $allStockIDs =  array_merge($stockIDs,$saleStockIDs);
        $tagListMap = SupplierCommodityTag::instance()->getTagNameListBySupplierCommodityIDs($allIDs);
        $stockUserMap = StockInfoUser::instance()->getStockUserByBidsAndIds($bid,$allStockIDs);
        foreach ($pageData as & $item ) {
            if( isset($SaleDataList[$item['SkuID']]) ) {
                $item = $SaleDataList[$item['SkuID']];
            }
            $item['Tags'] = json_encode($tagListMap[$item['SupplierCommodityID']] ?? [],JSON_UNESCAPED_UNICODE);
            $SpecList = @json_decode($item['SpecList'],true);
            $SpecList = array_map(function( $value ) use ($item){
                $value['SpecNum']   = (int)$value['SpecificationNum'];
                $value['specName']  = $value['SpecNum'].$item['UnitName']."装";
                $value['SpecPrice'] = (float)$value['SpecificationPrice'];
                $value['SpecFreightPrice'] = (float)($value['SpecificationFreightPrice']??$value['SpecificationPrice']);;
                unset($value['SpecificationNum'],$value['SpecificationPrice']);
                return $value;
            },$SpecList);
            $item['SpecList'] = json_encode($SpecList,JSON_UNESCAPED_UNICODE);
            $item['BatchMap'] = [$item['BatchNo'] => array_column($SpecList,null,'SpecNum')];
            //是否有锁定库存
            if (isset($stockUserMap[$item['StockInfoID']]))
            {
                $item['Number']=$stockUserMap[$item['StockInfoID']]['StockRemainNumber'];
            }
        }
        return $pageData;
    }
    
    /**
     * 子查询
     * @param int $bid
     * @param array $subQuery
     * @param array $where
     */
    public function getLastQuery(int $bid,$subQuery = [], $where = [] )
    {
        $table = CommodityOptimizationBbc::instance()->getTableByBuID($bid)->getTable();
        
        //路由模式需要授权所有商品
        $queryMain = CommodityOptimizationBbc::instance()->getTableByBuID($bid)
        ->from($table." AS cop")
        ->select($this->getGoodsColumns());
        
        //需要参加优选的商户
        $binfo = Business::instance()->getUserInfoByBid($bid);
        $isRouterUser = true;
        if ( ($bid > 0 && $binfo['is_router_user'] != 1) || $bid == 0 ) {
            $queryMain->joinSub($subQuery,"c",function($join){
                $join->on('c.max_id', '=', 'cop.ID');
            });
            
            $isRouterUser = false;
        }
        
        $join_mode = $isRouterUser ? 'leftJoin' : 'join';
        $queryMain->join("stockinfo_s2b as stock","stock.ID","=","cop.StockInfoID")
        ->join("commodityarchives_s2b as com","com.ID","=","stock.CommodityArchivesID")
        ->{$join_mode}("commoditydescription_s2b as cds",function($join){
            $join->on("cds.CommodityInfoID","=","com.ID")
            ->where("cds.IsDeleted",0);
        })->leftJoin("spuattr_s2b as spu","spu.ID","=","com.SpuID")
        ->join("suppliercommodity_s2b as scb","scb.ID","=","cop.SupplierSKUID")
        ->leftJoin("suppliercommoditycustominfo_s2b as scb_cus",function($join){
            $join->on("scb_cus.SupplierCommodityID","=","cop.SupplierSKUID")
            ->where("scb_cus.IsDeleted",0);
        })
        ->{$join_mode}("classifyinfo_s2b as f_class","f_class.ID","=","com.FirstClassificationID")
        ->{$join_mode}("classifyinfo_s2b as s_class","s_class.ID","=","com.SecondClassificationID")
        ->{$join_mode}("classifyinfo_s2b as t_class","t_class.ID","=","com.ThirdClassificationID")
        ->{$join_mode}("brandinfo_s2b as b","b.ID","=","com.BrandID")
        ->{$join_mode}("countryinfo_s2b as c","c.ID","=","com.CountryID")
        ->leftJoin("unitinfo_s2b as u","u.ID","=","com.UnitID")
        ->join("warehouseinfo_s2b as w","w.ID","=","stock.WarehouseID")
        ->join("suppliercompany_s2b as s","s.ID","=","stock.SupplierCompanyID");
        
        //如果是路由模式用户
        $whereRaw = implode(" AND ", $where);
        $whereRaw = str_replace("a_cop.","cop.", $whereRaw);
        $queryMain->whereRaw($whereRaw);
        
        return $queryMain->where('cop.BuID',$bid)
        ->orderBy("cop.ID","asc");
    }
    
    /**
     * 查询优先售卖商品
     * @param array $where
     */
    public function getSaleFirstQuery(int $bid , $where = [] )
    {
        $table = CommodityOptimizationBbc::instance()->getTableByBuID($bid)->getTable();
        $query = $this->getBestGoodsQuery($bid,$where);
        return CommodityOptimizationBbc::instance()->getTableByBuID($bid)
        ->from($table." as cop")
        ->select($this->getGoodsColumns())
        ->joinSub($query,"c",function($join){
            $join->on('cop.ID', '=', 'c.max_id');
        })
        ->join("stockinfo_s2b as stock","stock.ID","=","cop.StockInfoID")
        ->join("commodityarchives_s2b as com","com.ID","=","stock.CommodityArchivesID")
        ->join("commoditydescription_s2b as cds",function($join){
            $join->on("cds.CommodityInfoID","=","com.ID")
            ->where("cds.IsDeleted",0);
        })
        ->leftJoin("spuattr_s2b as spu","spu.ID","=","com.SpuID")
        ->join("suppliercommodity_s2b as scb","scb.ID","=","cop.SupplierSKUID")
        ->leftJoin("suppliercommoditycustominfo_s2b as scb_cus",function($join){
            $join->on("scb_cus.SupplierCommodityID","=","cop.SupplierSKUID")
            ->where("scb_cus.IsDeleted",0);
        })
        ->join("classifyinfo_s2b as f_class","f_class.ID","=","com.FirstClassificationID")
        ->join("classifyinfo_s2b as s_class","s_class.ID","=","com.SecondClassificationID")
        ->join("classifyinfo_s2b as t_class","t_class.ID","=","com.ThirdClassificationID")
        ->join("brandinfo_s2b as b","b.ID","=","com.BrandID")
        ->join("countryinfo_s2b as c","c.ID","=","com.CountryID")
        ->leftJoin("unitinfo_s2b as u","u.ID","=","com.UnitID")
        ->join("warehouseinfo_s2b as w","w.ID","=","stock.WarehouseID")
        ->join("suppliercompany_s2b as s","s.ID","=","stock.SupplierCompanyID")
        ->orderBy("cop.ID","asc")
        ->get()
        ->toArray();
    }
    
    /**
     * 获取优选模板SQL
     * @param string $bid
     * @param array $where
     */
    public function getBestGoodsQuery( int $bid = 0 , $where = [] )
    {
        $table = CommodityOptimizationBbc::instance()->getTableByBuID($bid)->getTable();
        $minPriceSubQuery = CommodityOptimizationBbc::instance()->getTableByBuID($bid)
        ->from($table . " as a_cop")
        ->select([
            'a_cop.BuID',
            'a_cop.SkuID',
            Db::raw('min(a_cop.BatchSpecMinSinglePrice) AS BatchSpecMinSinglePrice')
        ])
        ->join("stockinfo_s2b as stock","stock.CommodityArchivesID","=","a_cop.SkuID")
        ->join("commodityarchives_s2b as com","com.ID","=","stock.CommodityArchivesID")
        ->join("suppliercommodity_s2b as scb","scb.ID","=","stock.SupplierCommodityID")
        ->whereRaw(implode(" AND ", $where))
        ->where('a_cop.CommodityStatus',1)
        ->groupBy("a_cop.SkuID");
        
        return CommodityOptimizationBbc::instance()->getTableByBuID($bid)
        ->from($table." AS b")
        ->select([
            Db::raw("max(b.ID) AS max_id")
        ])
        ->joinSub($minPriceSubQuery,"a",function($join){
            $join->on('a.SkuID', '=', 'b.SkuID')
            ->on('a.BuID','=','b.BuID')
            ->on('a.BatchSpecMinSinglePrice','=','b.BatchSpecMinSinglePrice');
        })
        ->groupBy("b.SkuID")
        ->where('b.CommodityStatus',1);
    }
    
    /**
     * 获取搜索优选和授权参数
     * @param $param
     */
    protected function getWhereParameters( $param = [] )
    {
        $where = [];
        //验证供应商商品类型
        if( !isset($param['bid']) ) {
            return Normal::returnCode(Normal::FAIL,"bid不能为空");
        }

        $bid = $param['bid'] ? $param['bid'] : 0 ;
        $where[] = "a_cop.BuID = {$param['bid']} AND a_cop.IsInit = 1";
        
        //如果是通过主档案ID搜索
        if( isset($param['isArchive'])  && !empty($param['IDS'])) {
            $string = "'" . implode("','", $param['IDS']) . "'";
            if( $param['isArchive'] ) {
                $where[] = "a_cop.SkuID in ({$string})";
            } else {
                $where[] = "a_cop.SupplierSKUID in ({$string})";
            }
        }
        
        //supplier_skucodes
        if( !empty($param['supplier_skucodes']) ) {
            $string = "'" . implode("','", $param['supplier_skucodes']) . "'";
            $where[] = "a_cop.SupplierSKUCode in ({$string})";
        }
        
        //skucodes
        if( !empty($param['skucodes']) ) {
            $string = "'" . implode("','", $param['skucodes']) . "'";
            $where[] = "com.SKUCode in ({$string})";
        }
        
        //goods_name
        if( !empty($param['goods_name']) ) {
            $goods_name = $param['goods_name'];
            $_get_multi_search = getMultiLikeByString("'",$goods_name,'com.Name');
            if( ! $_get_multi_search ) {
                $where[] = "com.Name like '%{$goods_name}%'";
            } else {
                $where[] = $_get_multi_search;
            }
        }
        
        //skucode
        if( !empty($param['skucode']) ) {
            $where[] = "com.SkuCode = '{$param['skucode']}'";
        }
        
        //barcode
        if( !empty($param['barcode']) ) {
            $where[] = "com.BarCode = '{$param['barcode']}'";
        }
        
        //barcodes
        if( !empty($param['barcodes']) ) {
            $string = "'" . implode("','", $param['barcodes']) . "'";
            $where[] = "com.BarCode in ({$string})";
        }
        
        //has_rate
        if( isset($param['has_rate']) && in_array($param['has_rate'],['0','1']) ) {
            $has_rate = (int)$param['has_rate'];
            $where[] = "scb.IsHaveTaxRate = {$has_rate}";
        }
        
        //is_free_postfree
        if( isset($param['is_free_postfree']) && in_array($param['is_free_postfree'],['0','1'])  ) {
            $is_free_postfree = (int)$param['is_free_postfree'];
            $where[] = "scb.IsFreeShipping = {$is_free_postfree}";
        }
        
        //skuids
        if( !empty($param['skuids']) ) {
            $string = implode(",", $param['skuids']);
            $where[] = "a_cop.SkuID IN({$string})";
        }
        
        //class_ids
        if( !empty($param['class_ids']) ) {
            $string = implode(",", $param['class_ids']);
            $where[] = "( com.FirstClassificationID IN({$string}) or com.SecondClassificationID IN({$string}) or com.ThirdClassificationID IN({$string}))";
        }
        
        //brand_ids
        if( !empty($param['brand_ids']) ) {
            $string = implode(",", $param['brand_ids']);
            $where[] = "com.BrandID IN({$string})";
        }
        
        //country_ids
        if( !empty($param['country_ids']) ) {
            $string = implode(",", $param['country_ids']);
            $where[] = "com.CountryID IN({$string})";
        }
        
        //commodity_types
        if( !empty($param['commodity_types']) ) {
            $string = implode(",", $param['commodity_types']);
            $where[] = "com.CommodityType IN({$string})";
        }

        //goods_ids
        if( !empty($param['goods_ids']) ) {
            $string = implode(",", $param['goods_ids']);
            $where[] = "com.ID IN({$string})";
        }

        //supplier_ids
        if( !empty($param['supplier_ids']) ) {
            $string = implode(",", $param['supplier_ids']);
            $where[] = "scb.SupplierCompanyID IN({$string})";
        }

        //whereOr // 多个条件搜索
        if( !empty($param['whereOr']) ) {
            $string_arr = [];
            foreach ($param['whereOr'] as $whereKey => $whereOr){
                $string_arr[] = $whereKey . ' '. $whereOr['method'] . ' "' . $whereOr['value'].'" ';
            }
            $string = implode(" OR ", $string_arr);
            $where[] = "( {$string} )";
        }
        return Normal::returnCode(Normal::SUC,"获取成功",$where);
    }
    
    /**
     * 获取授权比较字段
     * 供应商商品ID,库存，价格，规格，批次，限购数量、是否残次、校期
     */
    protected function getAuthCheckGoodsColumns()
    {
        return [
            Db::raw("CONCAT(com.ID,'') AS SkuID"),
            Db::raw("CONCAT(com.SKUCode,'') AS SKUCode"),
            Db::raw("CONCAT(cop.SupplierSKUCode,'') AS SupplierSKUCode"),
            Db::raw("CONCAT(cop.SupplierSKUID,'') AS SupplierSKUID"),
            Db::raw("CONCAT(cop.StockInfoID,'') AS StockInfoID"),
            Db::raw("CONCAT(outter_stb.SupplierCompanyID,'') AS SupplierCompanyID"),
            Db::raw("CONCAT(outter_stb.BatchID,'') AS BatchID"),
            Db::raw("IFNULL(outter_stb.LimitBuyCount,0) AS LimitBuyCount"),
            "outter_stb.BatchNo",
            "outter_stb.SpecList",
            Db::raw("IFNULL(outter_stb.CalibrationPeriodTime,'') AS CalibrationPeriodTime"),
            "outter_stb.BatchSpecMinSinglePrice",
            Db::raw("IFNULL(outter_stb.IsDefective,0) AS IsDefective"),
        ];
    }
    
    /**
     * 获取模板数据字段
     * @var array
     */
    protected function getGoodsColumns()
    {
        return [
            Db::raw("CONCAT(com.ID,'') as GoodsID"),
            "com.Name",
            "cds.Images",
            "cds.Description",
            "com.CommodityType",
            "com.BarCode",
            Db::raw("IFNULL(com.FreightTemplateID,0) as FreightTemplateID"),
            Db::raw("IFNULL(com.Weight,0.000) as Weight"),
            "com.SpuID",
            Db::raw("IFNULL(spu.SpuName,'') as SpuName"),
            Db::raw("IFNULL(spu.SpuCode,'') as SpuCode"),
            Db::raw("IFNULL(com.MarketPrice,0.00) as MarketPrice"),
            Db::raw("IFNULL(com.SpuSpecJsonBody,'') AS SpuSpecJsonBody"),
            Db::raw("CONCAT(com.ID,'') AS SkuID"),
            Db::raw("CONCAT(com.SKUCode,'') AS SKUCode"),
            Db::raw("CONCAT(stock.SupplierCommodityID,'') AS SupplierCommodityID"),
            "scb.SupplierCommoditySkuCode",
            Db::raw("CONCAT(stock.BatchID,'') AS BatchID"),
            Db::raw("CONCAT(stock.ID,'') AS StockInfoID"),
            "stock.BatchNo",
            Db::raw("IFNULL(stock.LimitBuyCount,0) AS LimitBuyCount"),
            Db::raw("IFNULL(stock.CalibrationPeriodTime,'') as CalibrationPeriodTime"),
            "stock.Number",
            "stock.IsDefective",
            "stock.NumberLock",
            "scb.IsFreeShipping",
            "scb.IsNeedIDCard",
            "scb.IsNeedUploadIDCard",
            "scb.IsNeedWeiXinPay",
            "scb.DefaultStock",
            "scb.DeclarePlanCode",
            "scb.DeliveryMethod",
            "scb.IsHaveTaxRate",
            "scb.SupplierCommoditySpec",
            Db::raw("IFNULL(scb.TaxRate,0.0000) as TaxRate"),
            Db::raw("IFNULL(scb.HSCode,'') as HSCode"),
            "scb.PriceControlType",
            "scb.LimitOrControlPrice",
            Db::raw("CONCAT(cop.ID,'') as CopID"),
            "cop.SpecList",
            "cop.IsPriceSet",
            "cop.PriceScaleRule",
            "cop.PriceRuleType",
            "cop.IsAuth",
            "cop.IsInit",
            "cop.BatchSpecMinSinglePrice",
            Db::raw("CONCAT(cop.StockInfoID,'') as CopStockInfoID"),
            Db::raw("CONCAT(cop.BatchSpecMinSinglePrice,'') as CopBatchSpecMinSinglePrice"),
            Db::raw("CONCAT(cop.BatchNo,'') as CopBatchNo"),
            Db::raw("CONCAT(w.ID,'') as WarehouseID"),
            "w.WarehouseAccount",
            "w.WarehouseCode",
            "w.WarehouseName",
            "w.WarehouseType",
            Db::raw("IFNULL(w.IsCombineOrders,0) as IsCombineOrders"),
            "w.JsonBody",
            Db::raw("CONCAT(s.ID,'') as SupplierID"),
            "s.SupplierName",
            "s.SupplierCode",
            "s.SupplierAlias",
            "s.OrderDeclare",
            "s.PayDeclare",
            "s.SettlementMethod",
            "s.OrderDockMode",
            "s.CompanyStatus",
            "s.IsWholesaler",
            "s.ThirdPartyPlatformCode",
            "s.BusinessLicenseNo",
            "s.FastDeliveryType",
            Db::raw("IFNULL(s.EnterpriseName,'') as EnterpriseName"),
            Db::raw("IFNULL(s.EnterpriseCode,'') as EnterpriseCode"),
            Db::raw("CONCAT(f_class.ID,'') as FirstClassificationID"),
            "f_class.ClassificationCode as FirstClassificationCode",
            "f_class.ClassificationName as FirstClassificationName",
            Db::raw("CONCAT(s_class.ID,'') as SecondClassificationID"),
            "s_class.ClassificationCode as SecondClassificationCode",
            "s_class.ClassificationName as SecondClassificationName",
            Db::raw("CONCAT(t_class.ID,'') as ThirdClassificationID"),
            "t_class.ClassificationCode as ThirdClassificationCode",
            "t_class.ClassificationName as ThirdClassificationName",
            Db::raw("CONCAT(b.ID,'') AS BrandID"),
            "b.BrandCode",
            "b.BrandName",
            Db::raw("CONCAT(c.ID,'') AS CountryID"),
            "c.CountryCode",
            "c.CountryName",
            Db::raw("CONCAT(u.ID,'') as UnitID"),
            "u.UnitCode",
            "u.Name as UnitName",
            "scb_cus.Country as DeclareCountry",
            "scb_cus.CountryCode AS DeclareCountryCode",
            "scb_cus.Currency as DeclareCurrency",
            "scb_cus.CurrencyCode as DeclareCurrencyCode",
            "scb_cus.DeclareBarCode",
            "scb_cus.DeclareCommodityName",
            "scb_cus.DeclareSKUCode",
            "scb_cus.Function as DeclareFunction",
            "scb_cus.MeasurementUnit as DeclareMeasurementUnit",
            "scb_cus.MeasurementUnitCode as DeclareMeasurementUnitCode",
            "scb_cus.Specifications as DeclareSpecifications",
            "scb.CommodityCommissionLevelJsonBody as CommissionLevelList",
            "scb.LimitPriceMode",
            "scb.LimitPriceScale",
            'scb.ConSumptionTaxRate',
            'scb.ConSumptionPrice',
            'scb.CustomID'
        ];
    }
    
    /**
     * 获取推送数据的价格模板处理
     * @param array $binfo 商户信息
     * @param array $tplInfo  Template表指定价格模板id的数据
     * @param array $goodsList  商品sku信息
     * @return mixed
     */
    public function getUserAuthGoodsList( array $binfo = [] ,array $tplInfo = [],array $goodsList = [] )
    {
        //是否给下游统一推送建议零售价
        $is_market_price_send = $binfo['is_market_price_send'];
        $dataList = [];
        foreach ($goodsList as $skuInfo )
        {
            //处理规格问题
            $spec = $this->getGoodsSpecList($skuInfo,json_encode($tplInfo),$binfo);
            $specList = $spec['SpecList'];
            $specList = array_map(function( & $value ) use ($is_market_price_send){
                unset($value['priceCost']);
                if( $is_market_price_send == 1 ) {
                    $value['priceSettlement'] = $value['price'];
                }
                return $value;
            }, $specList);
            $dataList[] = [
                'goods_id'  => $skuInfo['SkuID'],
                'skucode'   => $skuInfo['skuCode'],
                'barcode'   => $skuInfo['BarCode'],
                'spec_list' => json_encode($specList,JSON_UNESCAPED_UNICODE),
            ];            
        }
        return $dataList;
    }
    
    /**
     * 处理下游标准规格结构
     * @param array $skuInfo
     * @param array $priceInfo
     */
    public function getGoodsSpecList($skuInfo = [] ,$priceInfo = [],$bInfo=[] )
    {
        $specList = $skuInfo['SpecList'];
        if( is_string($specList) ) {
            $specListNew = @json_decode($specList,true);
            $specList = array_map(function( & $value ){
                $value['SpecificationNum']      = $value['SpecNum'];
                $value['SpecificationPrice']    = $value['SpecPrice'];
                $value['SpecificationFreightPrice']    = $value['SpecFreightPrice']??$value['SpecPrice'];
                unset($value['SpecPrice'],$value['SpecNum']);
                return $value;
            },$specListNew);
        }
        
        $newSpecList = [];
        foreach ($specList as $item )
        {
            $isPriceControl     = in_array($skuInfo['PriceControlType'],[1,2]) ? true : false ;
            $controlPrice       = (float)$skuInfo['LimitOrControlPrice'];
            $specificationNum   = (int)$item['SpecificationNum'];
            $specificationPrice = (float)($item['SpecificationFreightPrice']??$item['SpecificationPrice']);
            if ($bInfo['user_tax_mode'] != 0){
                $specificationPrice = $this->changeTaxPrice($specificationPrice,$bInfo['user_tax_mode'],$skuInfo['isHaveTaxRate'],$skuInfo['taxRate']);
            }

            $marketPrice        = $skuInfo['MarketPrice'];//市场单价
            $singleSpecPrice    = bcdiv((string)$specificationPrice, (string)$specificationNum,2);
            $spec = [
                "spec_num"    	=> $specificationNum,
                "specName"    	=> $skuInfo['UnitName'],
                "expired_date"	=> MyDate::getDateByMysqlDateFields($skuInfo['CalibrationPeriodTime']),
                "make_date"   	=> '',
                "price"       	=> $specificationPrice,
                "priceCost"   	=> (float)$specificationPrice,
                "priceControl"	=> bcmul((string)$specificationNum,(string)$controlPrice,2),
                'singlePrice' 	=> bcmul((string)$singleSpecPrice, '100'),
            ];
    
            //限价、控价商品乘以对应的规格数量
            if( $isPriceControl ) {
                $calc_spec = [
                    'price'             => $specificationPrice,
                    'priceSettlement'   => $specificationPrice,
                    'priceMarket'       => $specificationPrice,
                ];
            } else if( $skuInfo['PriceRuleType'] == 1 ) {//独立的价格比列
                $calc_spec = $this->calcPriceByTemplate($skuInfo,$skuInfo['PriceScaleRule'],$spec);
            } else if( $skuInfo['PriceRuleType'] == 2 && isset($item['price_rate']) && isset($item['price_settlement_rate']) && isset($item['price_market_rate'])) {//独立设置价格
                $calc_spec = [
                    'price'             => $item['price_rate'],
                    'priceSettlement'   => $item['price_settlement_rate'],
                    'priceMarket'       => $item['price_market_rate'],
                ];
            } else {
                $calc_spec = $this->calcPriceByTemplate($skuInfo,$priceInfo,$spec);
            }
                
            //如果设置了建议零售价，统一乘以对应的规格值进行计算
            if( !empty($skuInfo['MarketPrice']) && $skuInfo['MarketPrice'] > 0 )
            {
                $calc_spec['price'] = $calc_spec['priceMarket'] = bcmul((string)$skuInfo['MarketPrice'],(string)$specificationNum,2);
            }
            
            //合并计算后的价格
            $newSpecList[] = array_merge($spec,$calc_spec);
        }
    
        //寻找最大值和最小值
        $singlePrices  = array_column($newSpecList, 'singlePrice');
        $minPrice      = min($singlePrices);
        $isMinStockSpecificationItem = false;
        foreach ($newSpecList as & $item )
        {
            if( $item['singlePrice'] == $minPrice && $isMinStockSpecificationItem == false ) {
                $item['isMinStockSpecificationItem'] = true;
            } else {
                $item['isMinStockSpecificationItem'] = false;
            }
            unset($item['singlePrice']);
        }
    
        return [
            'minSinglePrice'    => $minPrice,
            'maxSinglePrice'    => max($singlePrices),
            'SpecList'          => $newSpecList
        ];
    }
    
    /**
     * 根据不同价格模板计算价格
     * @param array $skuInfo
     * @param array $price_contents
     * @param array $spec
     * @return mixed
     */
    public function calcPriceByTemplate( $skuInfo = [] , $price_contents = [] , $spec = [] )
    {
        //商品成本规格价格
        $spec_price     = $spec['price'];
        $price_contents = @json_decode($price_contents,true);
        return [
            'price'             => $this->calcPriceFloat(bcmul($spec_price, bcadd(self::BASE_PRICE_RATE,bcdiv($price_contents['price_rate'], 100,self::BASE_SCALE_TYPE),self::BASE_SCALE_TYPE),self::BASE_FLOAT)),
            'priceSettlement'   => $this->calcPriceFloat(bcmul($spec_price, bcadd(self::BASE_PRICE_RATE,bcdiv($price_contents['price_settlement_rate'], 100,self::BASE_SCALE_TYPE),self::BASE_SCALE_TYPE),self::BASE_FLOAT)),
            'priceMarket'       => $this->calcPriceFloat(bcmul($spec_price, bcadd(self::BASE_PRICE_RATE,bcdiv($price_contents['price_market_rate'], 100,self::BASE_SCALE_TYPE),self::BASE_SCALE_TYPE),self::BASE_FLOAT)),
        ];
        
    }

    /**
     * 价格计算向上取值
     * @param $price
     * @return string|null
     */
    public function calcPriceFloat($price)
    {
        $mulPrice = ceil(bcmul((string)$price,'100',1));
        return bcdiv((string)$mulPrice,'100',2);
    }

    /**
     * 根据填写的包邮模型来修改价格
     * @param $price
     * @param $taxMode
     * @param $isHaveTax
     * @param $taxRate
     * @return string
     */
    public function changeTaxPrice($price,$taxMode,$isHaveTax,$taxRate)
    {
        $tax_rate = bcadd((string)$taxRate,'1.0000',4);
        if ($taxMode == 1 && $isHaveTax == 0){
            //需要改为含税价
            $price = bcmul((string)$price,$tax_rate,2);
        }elseif ($taxMode==2 && $isHaveTax==1){
            //需要改为不含税价
            $price = bcdiv((string)$price,$tax_rate,3);
            $price = bcmul((string)$price,'100',1);
            $price = bcdiv((string)ceil($price),'100',2);
        }
        return $price;
    }
    
    /**
     * 下单调度动态切换供应商商品，最大限度保证下单成功
     * 如果当前批次下单不成功的话，会切换到优选里面满足条件的其它供应商商品
     * 优先售卖为先，之后价格最低为先，同时满足规格数量能和下单一致就可以进行自动切换
     * @param int $bid 
     * @param array $goods_list
     * @param bool $isBbcOrder
     * @param bool $is_router_user 是否路由模式商品
     */
    public function getRealGoodsList( $bid = 0,$goods_list = [],$isBbcOrder = false ,$is_router_user = 0 )
    {
        if( $is_router_user == 0 ) {
            $SkuIds = array_column($goods_list,'goods_id');
        } else {
            $SkuIds = array_column($goods_list,'skucode');//编码当成ID
        }
        
        //实际调度的商品
        $dispatchBackUpGoodsList = $this->getDispatchBackUpGoodsList($bid,$SkuIds,$is_router_user);
        $orderDispatchGoods = [];
        foreach ($goods_list as $goods_item )
        {
            $SkuId      = $goods_item['goods_id'];
            $batch_no   = $goods_item['batch_no'];
            $spec_num   = $goods_item['spec_num'];
            $goods_num  = $goods_item['goods_num'];
            $buy_number = $goods_num * $spec_num;
            if( !isset($dispatchBackUpGoodsList[$SkuId]) ) {
                
                if( $isBbcOrder ) {
                    return Normal::returnCode(Normal::FAIL,"当前优选商品『{$goods_item['skucode']}』已下架,请重新选购商品！100000");
                }
                
                return Normal::returnCode(Normal::FAIL,"当前优选商品『{$goods_item['goods_name']}』已下架,请重新选购商品！100001");
            }
            
            $currentGoods = $dispatchBackUpGoodsList[$SkuId];
            //优选售卖商品
            $saleFirstGoods = $currentGoods[1] ?? [];
            if( !empty($saleFirstGoods) ) {
                //寻找满足条件的数据
                foreach ($saleFirstGoods as $item )
                {
                    $SpecList = array_column($item['SpecList'],'SpecificationPrice','SpecificationNum');
                    $Number   = $item['number'];
                    //满足库存和规格
                    if( $Number >= $buy_number && isset($SpecList[$spec_num]) ) {
                        $orderDispatchGoods[$SkuId] = $item;
                    }
                }
            }
    
            //正常优选商品
            $saleNormalGoods = $currentGoods[0] ?? [] ;
            if( !empty($saleNormalGoods) )
            {
                //寻找满足条件的数据
                foreach ($saleNormalGoods as $item )
                {
                    $SpecList = array_column($item['SpecList'],'SpecificationPrice','SpecificationNum');
                    $Number   = $item['number'];
                    //满足库存和规格
                    if( !isset($orderDispatchGoods[$SkuId]) && $Number >= $buy_number && isset($SpecList[$spec_num]) ) {
                        $orderDispatchGoods[$SkuId] = $item;
                    }
                }
            }
            
            //未找到满足条件的供应商商品
            if( empty($orderDispatchGoods[$SkuId]) ) {
                if( $isBbcOrder ) {
                    return Normal::returnCode(Normal::FAIL,"当前优选商品『{$goods_item['skucode']}』已下架,请重新选购商品！100002");
                }
                return Normal::returnCode(Normal::FAIL,"当前优选商品『{$goods_item['goods_name']},{$goods_item['skucode']}』已下架,请重新选购商品！100003");
            }
    
            unset($item);
        }
        return Normal::returnCode(Normal::SUC,"获取优选商品成功",$orderDispatchGoods);
    }
    
    /**
     * 获取推送数据的价格模板处理
     * @param array $binfo 商户信息
     * @param array $tplInfo  Template表指定价格模板id的数据
     * @param array $goodsList  商品sku信息
     * @param array $goodsLevelConfig 毛利编码配置
     * @param array $templateInfo 运费模板
     * @return mixed
     */
    public function getChannelPushGoodsByPriceTpl( array $binfo = [] ,array $tplInfo = [],array $goodsList = [],array $goodsLevelConfig = [],array $templateInfo = [] )
    {
        //是否给下游统一推送建议零售价
        //获取所有运费模板ID
        $FreightTemplateIDs = array_filter(array_unique(array_column($goodsList, 'FreightTemplateID')));
        $goodsFreightTemplateLists = TemplateDelivery::instance()->getMultiGoodsTemplateListsByTemplateIds($FreightTemplateIDs);
        $is_market_price_send = $binfo['is_market_price_send'];
        $dataList = [];
        foreach ($goodsList as $skuInfo )
        {
            //处理规格问题
            $spec = $this->getGoodsSpecList($skuInfo,$tplInfo,$binfo);
            $specList = $spec['SpecList'];
            $specList = array_map(function( & $value ) use ($is_market_price_send){
                unset($value['priceCost']);
                if( $is_market_price_send == 1 ) {
                    $value['priceSettlement'] = $value['price'];
                }
                return $value;
            }, $specList);
            $firstSpec = current($specList);
            
            //处理图片
            $Images         = @json_decode($skuInfo['Images'],true);
            $images         = QueryGoodsMicService::instance()->getResetImagesList($Images);
            //毛利编码
            $goodsLevel     = $this->getGoodsLevel($skuInfo['MarketPrice'],$spec['maxSinglePrice'],$goodsLevelConfig);
            //商品类型
            $commodity_type = $skuInfo['CommodityType'];
            $goodsTypeName  = isset($this->goodsType[$commodity_type]) ? $this->goodsType[$commodity_type] : '未定义';
            $commodity_customer_info = [
                'payDeclare'                    => $skuInfo['PayDeclare'],
                'payDeclareEnumDescription'     => $skuInfo['PayDeclare'] == 1 ? '需要支付单申报' : '',
                'orderDeclare'                  => $skuInfo['OrderDeclare'],
                'orderDeclareEnumDescription'   => $skuInfo['OrderDeclare'] == 1 ? '需要订单申报' : '',
                'enterpriseName'                => $skuInfo['EnterpriseName'],
                'enterpriseCode'                => $skuInfo['EnterpriseCode'],
                'declareSKUCode'                => $skuInfo['DeclareSKUCode'],
                'declareCommodityName'          => $skuInfo['DeclareCommodityName'],
                'function'                      => $skuInfo['DeclareSKUCode'],
                'declareBarCode'                => $skuInfo['DeclareBarCode'],
                'customMeasurementUnitCode'     => $skuInfo['DeclareMeasurementUnitCode'],
                'customMeasurementUnit'         => $skuInfo['DeclareMeasurementUnit'],
                'customCountryCode'             => $skuInfo['DeclareCountryCode'],
                'customCountry'                 => $skuInfo['DeclareCountry'],
                'customCurrencyCode'            => $skuInfo['DeclareCurrencyCode'],
                'customCurrency'                => $skuInfo['DeclareCurrency'],
                'customSpecifications'          => $skuInfo['DeclareSpecifications'],
            ];

            //处理spu属性贵格问题
            $spuSpecJsonBody = @json_decode($skuInfo['SpuSpecJsonBody'],true);

            //商品运费模板ID
            $FreightTemplateID = $skuInfo['FreightTemplateID'];
            $freight_template = isset($goodsFreightTemplateLists[$FreightTemplateID]) ? $goodsFreightTemplateLists[$FreightTemplateID] : $templateInfo;

            //处理规格库存问题
            $batch = [
                'supplier_skuid'    => $skuInfo['SupplierCommodityID'],
                'supplier_skucode'  => $skuInfo['SKUCode'],
                'defaultStock'      => $skuInfo['DefaultStock'],
                'num'               => $skuInfo['Number'],
                'batch_no'          => $skuInfo['BatchNo'],
                'batch_id'          => $skuInfo['BatchID'],
                'status'            => 1,
                'spec_list'         => $specList
            ];
            $goods_batch_list = [$batch];
            $store = [
                "linkSkuID"                     => $skuInfo['SkuID'],
                "store_customer_name"           => $skuInfo['PayDeclare'] == 1 ? $skuInfo['WarehouseName'] : '优选仓',
                "store_type"                    => $skuInfo['WarehouseType'],
                "storeDisplayName"              => $skuInfo['PayDeclare'] == 1 ? $skuInfo['WarehouseName'] : '优选仓',
                "store_id"                      => $skuInfo['WarehouseID'],
                "store_code"                    => $skuInfo['WarehouseCode'],
                "store_name"                    => $skuInfo['WarehouseName'],
                "store_account"                 => $skuInfo['WarehouseAccount'],
                "store_isCombineOrders"         => $skuInfo['IsCombineOrders'],
                "store_mode"                    => $skuInfo['OrderDockMode'],
                "supplier_skuid"                => $skuInfo['SupplierCommodityID'],
                "supplier_skucode"              => $skuInfo['SupplierCommoditySkuCode'],
                "supplier_id"                   => $skuInfo['SupplierID'],
                "supplier_alias"                => $skuInfo['SupplierAlias'],
                "supplier_code"                 => $skuInfo['SupplierCode'],
                "supplier_companystatus"        => $skuInfo['CompanyStatus'],
                "supplier_commoditydockmode"    => $skuInfo['OrderDockMode'],
                "supplier_stockdockmode"        => 0,
                "supplier_orderdockmode"        => 0,
                "goods_batch_list"              => $goods_batch_list
            ];
            $storeList = [$store];
            $dataList[] =[
                'goodsId'           => $skuInfo['GoodsID'],
                'goodsName'         => $skuInfo['Name'],
                'introName'         => $skuInfo['Name']."({$goodsTypeName})",
                'images'            => $images,
                'description'       => $skuInfo['Description'],
                'goodsType'         => $commodity_type,
                'goods_extends_type'=> $skuInfo['PriceControlType'],
                'goodsTypeName'     => $goodsTypeName,
                'status'            => 1,
                'categoryId'        => $skuInfo['SecondClassificationID'],
                'categoryCode'      => $skuInfo['SecondClassificationCode'],
                'categoryName'      => $skuInfo['SecondClassificationName'],
                'categoryId'        => $skuInfo['ThirdClassificationID'],
                'categoryCode'      => $skuInfo['ThirdClassificationCode'],
                'categoryName'      => $skuInfo['ThirdClassificationName'],
                'categoryPid'       => $skuInfo['SecondClassificationID'],
                'categoryPreCode'   => $skuInfo['SecondClassificationCode'],
                'categoryPreName'   => $skuInfo['SecondClassificationName'],
                'categoryFPid'      => $skuInfo['FirstClassificationID'],
                'categoryFPreCode'  => $skuInfo['FirstClassificationCode'],
                'categoryFPreName'  => $skuInfo['FirstClassificationName'],
                'categoryPreId'     => $skuInfo['FirstClassificationID'],
                'brandID'           => $skuInfo['BrandID'],
                'brandCode'         => $skuInfo['BrandCode'],
                'brandName'         => $skuInfo['BrandName'],
                'countryId'         => $skuInfo['CountryID'],
                'countryCode'       => $skuInfo['CountryCode'],
                'countryName'       => $skuInfo['CountryName'],
                'unitID'            => $skuInfo['UnitID'],
                'unitCode'          => $skuInfo['UnitCode'],
                'unitName'          => $skuInfo['UnitName'],
                'goods_level'       => $goodsLevel,
                'freight_template'  => $freight_template,
                'isFreePostFee'     => $skuInfo['IsFreeShipping'],
                'isNeedWeiXinPay'   => $skuInfo['IsNeedWeiXinPay'],
                'isNeedUploadIDCard'=> $skuInfo['IsNeedUploadIDCard'],
                'isNeedIDCard'      => $skuInfo['IsNeedIDCard'],
                'tags'              => @json_decode($skuInfo['Tags'],true),
                'skuList'           => [
                    [
                        'skuId'                     => $skuInfo['SkuID'],
                        'skucode'                   => $skuInfo['SKUCode'],
                        'barcode'                   => $skuInfo['BarCode'],
                        'tax_rate'                  => $skuInfo['TaxRate'],
                        'weight'                    => $skuInfo['Weight'],
                        'limit_buy_count'           => $skuInfo['LimitBuyCount'],
                        'has_rate'                  => $skuInfo['IsHaveTaxRate'],
                        'status'                    => 1,
                        'price'                     => $firstSpec['price'],
                        'price_cost'                => $firstSpec['priceSettlement'],
                        'price_market'              => $firstSpec['priceMarket'],
                        'price_control'             => $firstSpec['priceControl'],
                        'spu_id'                    => $skuInfo['SpuID'],
                        'spu_name'                  => $skuInfo['SpuName'],
                        'spu_code'                  => $skuInfo['SpuCode'],
                        'specList'                  => $spuSpecJsonBody,
                        'commodity_customer_info'   => $commodity_customer_info,
                        'storeList'                 => $storeList,
                    ]
                ],
            ];
        }
        return $dataList;
    }
    
    /**
     * 计算商品毛利编码
     * @param float $MarketPrice
     * @param float $MaxSinglePrice
     * @param array $goodsLevelConfig
     */
    public function getGoodsLevel(float $MarketPrice, float $MaxSinglePrice,$goodsLevelConfig)
    {
        $MarketPrice = bcdiv((string)$MarketPrice, 100,2);
        $MaxSinglePrice = bcdiv((string)$MaxSinglePrice, 100,2);
        $bcsub_value = bcsub((string)$MarketPrice, (string)$MaxSinglePrice,2);
        krsort($goodsLevelConfig);
    
        $lv = '';
        foreach ($goodsLevelConfig as $level_price => $goods_level )
        {
            if( $bcsub_value >= $level_price ) {
                $lv = $goods_level;
                break;
            }
        }
    
        $last = end($goodsLevelConfig);
        if( !$lv ) {
            $lv = $last;
        }
        return $lv;
    }

    /**
     * 通过供应商商品编码获取商品调度信息
     * @param int $bid
     * @param string $supplierSkuCode
     */
    public function getBestGoodsBySupplierCodes( int $bid , string $supplierSkuCode )
    {
        $goodsRows = CommodityOptimizationBbc::instance()->getCopListByBuIDAndSupplierSkuCodes($bid,[(string)$supplierSkuCode]);
        if( empty($goodsRows) ) {
            return Normal::returnCode(Normal::FAIL,"商品获取失败:SupplierSkuCodes【".$supplierSkuCode."】");
        }
        return Normal::returnCode(Normal::SUC,"操作成功",array_column($goodsRows,null,'SupplierSKUCode'));
    }


    /**
     * 通过商品编码获取商品调度信息支持单个
     * @param int $bid
     * @param string $skuCode
     */
    public function getBestGoodsBySkuCodes( int $bid , string $skuCode )
    {
        $goodsRows = CommodityOptimizationBbc::instance()->getCopListByBuIDAndSkuCodes($bid,[(string)$skuCode]);
        if( empty($goodsRows) ) {
            return Normal::returnCode(Normal::FAIL,"商品获取失败:skuCode【".$skuCode."】");
        }
        return Normal::returnCode(Normal::SUC,"操作成功",array_column($goodsRows,null,'SKUCode'));
    }
}